
<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta charset="utf-8" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />

    <title>zipapp — Manage executable Python zip archives &#8212; Python 3.9.6 documentation</title>
    <link rel="stylesheet" href="../_static/pydoctheme.css" type="text/css" />
    <link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
    
    <script type="text/javascript" id="documentation_options" data-url_root="../" src="../_static/documentation_options.js"></script>
    <script type="text/javascript" src="../_static/jquery.js"></script>
    <script type="text/javascript" src="../_static/underscore.js"></script>
    <script type="text/javascript" src="../_static/doctools.js"></script>
    <script type="text/javascript" src="../_static/language_data.js"></script>
    
    <script type="text/javascript" src="../_static/sidebar.js"></script>
    
    <link rel="search" type="application/opensearchdescription+xml"
          title="Search within Python 3.9.6 documentation"
          href="../_static/opensearch.xml"/>
    <link rel="author" title="About these documents" href="../about.html" />
    <link rel="index" title="Index" href="../genindex.html" />
    <link rel="search" title="Search" href="../search.html" />
    <link rel="copyright" title="Copyright" href="../copyright.html" />
    <link rel="next" title="Python Runtime Services" href="python.html" />
    <link rel="prev" title="venv — Creation of virtual environments" href="venv.html" />
    <link rel="canonical" href="https://docs.python.org/3/library/zipapp.html" />
    
      
      
    

    
    <style>
      @media only screen {
        table.full-width-table {
            width: 100%;
        }
      }
    </style>

    <link rel="shortcut icon" type="image/png" href="../_static/py.png" />
    
    <script type="text/javascript" src="../_static/copybutton.js"></script>
    
     


  </head><body>
  
    <div class="related" role="navigation" aria-label="related navigation">
      <h3>Navigation</h3>
      <ul>
        <li class="right" style="margin-right: 10px">
          <a href="../genindex.html" title="General Index"
             accesskey="I">index</a></li>
        <li class="right" >
          <a href="../py-modindex.html" title="Python Module Index"
             >modules</a> |</li>
        <li class="right" >
          <a href="python.html" title="Python Runtime Services"
             accesskey="N">next</a> |</li>
        <li class="right" >
          <a href="venv.html" title="venv — Creation of virtual environments"
             accesskey="P">previous</a> |</li>

    <li><img src="../_static/py.png" alt=""
             style="vertical-align: middle; margin-top: -1px"/></li>
    <li><a href="https://www.python.org/">Python</a> &#187;</li>
    

    <li>
      <a href="../index.html">3.9.6 Documentation</a> &#187;
    </li>

          <li class="nav-item nav-item-1"><a href="index.html" >The Python Standard Library</a> &#187;</li>
          <li class="nav-item nav-item-2"><a href="distribution.html" accesskey="U">Software Packaging and Distribution</a> &#187;</li>
    <li class="right">
        

    <div class="inline-search" style="display: none" role="search">
        <form class="inline-search" action="../search.html" method="get">
          <input placeholder="Quick search" type="text" name="q" />
          <input type="submit" value="Go" />
          <input type="hidden" name="check_keywords" value="yes" />
          <input type="hidden" name="area" value="default" />
        </form>
    </div>
    <script type="text/javascript">$('.inline-search').show(0);</script>
         |
    </li>

      </ul>
    </div>    

    <div class="document">
      <div class="documentwrapper">
        <div class="bodywrapper">
          <div class="body" role="main">
            
  <section id="module-zipapp">
<span id="zipapp-manage-executable-python-zip-archives"></span><h1><a class="reference internal" href="#module-zipapp" title="zipapp: Manage executable Python zip archives"><code class="xref py py-mod docutils literal notranslate"><span class="pre">zipapp</span></code></a> — Manage executable Python zip archives<a class="headerlink" href="#module-zipapp" title="Permalink to this headline">¶</a></h1>
<div class="versionadded">
<p><span class="versionmodified added">New in version 3.5.</span></p>
</div>
<p><strong>Source code:</strong> <a class="reference external" href="https://github.com/python/cpython/tree/3.9/Lib/zipapp.py">Lib/zipapp.py</a></p>
<hr class="docutils" id="index-0" />
<p>This module provides tools to manage the creation of zip files containing
Python code, which can be  <a class="reference internal" href="../using/cmdline.html#using-on-interface-options"><span class="std std-ref">executed directly by the Python interpreter</span></a>.  The module provides both a
<a class="reference internal" href="#zipapp-command-line-interface"><span class="std std-ref">Command-Line Interface</span></a> and a <a class="reference internal" href="#zipapp-python-api"><span class="std std-ref">Python API</span></a>.</p>
<section id="basic-example">
<h2>Basic Example<a class="headerlink" href="#basic-example" title="Permalink to this headline">¶</a></h2>
<p>The following example shows how the <a class="reference internal" href="#zipapp-command-line-interface"><span class="std std-ref">Command-Line Interface</span></a>
can be used to create an executable archive from a directory containing
Python code.  When run, the archive will execute the <code class="docutils literal notranslate"><span class="pre">main</span></code> function from
the module <code class="docutils literal notranslate"><span class="pre">myapp</span></code> in the archive.</p>
<div class="highlight-shell-session notranslate"><div class="highlight"><pre><span></span><span class="gp">$ </span>python -m zipapp myapp -m <span class="s2">&quot;myapp:main&quot;</span>
<span class="gp">$ </span>python myapp.pyz
<span class="go">&lt;output from myapp&gt;</span>
</pre></div>
</div>
</section>
<section id="command-line-interface">
<span id="zipapp-command-line-interface"></span><h2>Command-Line Interface<a class="headerlink" href="#command-line-interface" title="Permalink to this headline">¶</a></h2>
<p>When called as a program from the command line, the following form is used:</p>
<div class="highlight-shell-session notranslate"><div class="highlight"><pre><span></span><span class="gp">$ </span>python -m zipapp <span class="nb">source</span> <span class="o">[</span>options<span class="o">]</span>
</pre></div>
</div>
<p>If <em>source</em> is a directory, this will create an archive from the contents of
<em>source</em>.  If <em>source</em> is a file, it should be an archive, and it will be
copied to the target archive (or the contents of its shebang line will be
displayed if the –info option is specified).</p>
<p>The following options are understood:</p>
<dl class="cmdoption">
<dt id="cmdoption-zipapp-o">
<code class="sig-name descname">-o</code><code class="sig-prename descclassname"> &lt;output&gt;</code><code class="sig-prename descclassname">, </code><code class="sig-name descname">--output</code><code class="sig-prename descclassname">=&lt;output&gt;</code><a class="headerlink" href="#cmdoption-zipapp-o" title="Permalink to this definition">¶</a></dt>
<dd><p>Write the output to a file named <em>output</em>.  If this option is not specified,
the output filename will be the same as the input <em>source</em>, with the
extension <code class="docutils literal notranslate"><span class="pre">.pyz</span></code> added.  If an explicit filename is given, it is used as
is (so a <code class="docutils literal notranslate"><span class="pre">.pyz</span></code> extension should be included if required).</p>
<p>An output filename must be specified if the <em>source</em> is an archive (and in
that case, <em>output</em> must not be the same as <em>source</em>).</p>
</dd></dl>

<dl class="cmdoption">
<dt id="cmdoption-zipapp-p">
<code class="sig-name descname">-p</code><code class="sig-prename descclassname"> &lt;interpreter&gt;</code><code class="sig-prename descclassname">, </code><code class="sig-name descname">--python</code><code class="sig-prename descclassname">=&lt;interpreter&gt;</code><a class="headerlink" href="#cmdoption-zipapp-p" title="Permalink to this definition">¶</a></dt>
<dd><p>Add a <code class="docutils literal notranslate"><span class="pre">#!</span></code> line to the archive specifying <em>interpreter</em> as the command
to run.  Also, on POSIX, make the archive executable.  The default is to
write no <code class="docutils literal notranslate"><span class="pre">#!</span></code> line, and not make the file executable.</p>
</dd></dl>

<dl class="cmdoption">
<dt id="cmdoption-zipapp-m">
<code class="sig-name descname">-m</code><code class="sig-prename descclassname"> &lt;mainfn&gt;</code><code class="sig-prename descclassname">, </code><code class="sig-name descname">--main</code><code class="sig-prename descclassname">=&lt;mainfn&gt;</code><a class="headerlink" href="#cmdoption-zipapp-m" title="Permalink to this definition">¶</a></dt>
<dd><p>Write a <code class="docutils literal notranslate"><span class="pre">__main__.py</span></code> file to the archive that executes <em>mainfn</em>.  The
<em>mainfn</em> argument should have the form “pkg.mod:fn”, where “pkg.mod” is a
package/module in the archive, and “fn” is a callable in the given module.
The <code class="docutils literal notranslate"><span class="pre">__main__.py</span></code> file will execute that callable.</p>
<p><a class="reference internal" href="#cmdoption-zipapp-m"><code class="xref std std-option docutils literal notranslate"><span class="pre">--main</span></code></a> cannot be specified when copying an archive.</p>
</dd></dl>

<dl class="cmdoption">
<dt id="cmdoption-zipapp-c">
<code class="sig-name descname">-c</code><code class="sig-prename descclassname"></code><code class="sig-prename descclassname">, </code><code class="sig-name descname">--compress</code><code class="sig-prename descclassname"></code><a class="headerlink" href="#cmdoption-zipapp-c" title="Permalink to this definition">¶</a></dt>
<dd><p>Compress files with the deflate method, reducing the size of the output
file. By default, files are stored uncompressed in the archive.</p>
<p><a class="reference internal" href="#cmdoption-zipapp-c"><code class="xref std std-option docutils literal notranslate"><span class="pre">--compress</span></code></a> has no effect when copying an archive.</p>
<div class="versionadded">
<p><span class="versionmodified added">New in version 3.7.</span></p>
</div>
</dd></dl>

<dl class="cmdoption">
<dt id="cmdoption-zipapp-info">
<code class="sig-name descname">--info</code><code class="sig-prename descclassname"></code><a class="headerlink" href="#cmdoption-zipapp-info" title="Permalink to this definition">¶</a></dt>
<dd><p>Display the interpreter embedded in the archive, for diagnostic purposes.  In
this case, any other options are ignored and SOURCE must be an archive, not a
directory.</p>
</dd></dl>

<dl class="cmdoption">
<dt id="cmdoption-zipapp-h">
<code class="sig-name descname">-h</code><code class="sig-prename descclassname"></code><code class="sig-prename descclassname">, </code><code class="sig-name descname">--help</code><code class="sig-prename descclassname"></code><a class="headerlink" href="#cmdoption-zipapp-h" title="Permalink to this definition">¶</a></dt>
<dd><p>Print a short usage message and exit.</p>
</dd></dl>

</section>
<section id="python-api">
<span id="zipapp-python-api"></span><h2>Python API<a class="headerlink" href="#python-api" title="Permalink to this headline">¶</a></h2>
<p>The module defines two convenience functions:</p>
<dl class="function">
<dt id="zipapp.create_archive">
<code class="sig-prename descclassname">zipapp.</code><code class="sig-name descname">create_archive</code><span class="sig-paren">(</span><em class="sig-param">source</em>, <em class="sig-param">target=None</em>, <em class="sig-param">interpreter=None</em>, <em class="sig-param">main=None</em>, <em class="sig-param">filter=None</em>, <em class="sig-param">compressed=False</em><span class="sig-paren">)</span><a class="headerlink" href="#zipapp.create_archive" title="Permalink to this definition">¶</a></dt>
<dd><p>Create an application archive from <em>source</em>.  The source can be any
of the following:</p>
<ul class="simple">
<li><p>The name of a directory, or a <a class="reference internal" href="../glossary.html#term-path-like-object"><span class="xref std std-term">path-like object</span></a> referring
to a directory, in which case a new application archive will be
created from the content of that directory.</p></li>
<li><p>The name of an existing application archive file, or a <a class="reference internal" href="../glossary.html#term-path-like-object"><span class="xref std std-term">path-like object</span></a>
referring to such a file, in which case the file is copied to
the target (modifying it to reflect the value given for the <em>interpreter</em>
argument).  The file name should include the <code class="docutils literal notranslate"><span class="pre">.pyz</span></code> extension, if required.</p></li>
<li><p>A file object open for reading in bytes mode.  The content of the
file should be an application archive, and the file object is
assumed to be positioned at the start of the archive.</p></li>
</ul>
<p>The <em>target</em> argument determines where the resulting archive will be
written:</p>
<ul class="simple">
<li><p>If it is the name of a file, or a <a class="reference internal" href="../glossary.html#term-path-like-object"><span class="xref std std-term">path-like object</span></a>,
the archive will be written to that file.</p></li>
<li><p>If it is an open file object, the archive will be written to that
file object, which must be open for writing in bytes mode.</p></li>
<li><p>If the target is omitted (or <code class="docutils literal notranslate"><span class="pre">None</span></code>), the source must be a directory
and the target will be a file with the same name as the source, with
a <code class="docutils literal notranslate"><span class="pre">.pyz</span></code> extension added.</p></li>
</ul>
<p>The <em>interpreter</em> argument specifies the name of the Python
interpreter with which the archive will be executed.  It is written as
a “shebang” line at the start of the archive.  On POSIX, this will be
interpreted by the OS, and on Windows it will be handled by the Python
launcher.  Omitting the <em>interpreter</em> results in no shebang line being
written.  If an interpreter is specified, and the target is a
filename, the executable bit of the target file will be set.</p>
<p>The <em>main</em> argument specifies the name of a callable which will be
used as the main program for the archive.  It can only be specified if
the source is a directory, and the source does not already contain a
<code class="docutils literal notranslate"><span class="pre">__main__.py</span></code> file.  The <em>main</em> argument should take the form
“pkg.module:callable” and the archive will be run by importing
“pkg.module” and executing the given callable with no arguments.  It
is an error to omit <em>main</em> if the source is a directory and does not
contain a <code class="docutils literal notranslate"><span class="pre">__main__.py</span></code> file, as otherwise the resulting archive
would not be executable.</p>
<p>The optional <em>filter</em> argument specifies a callback function that
is passed a Path object representing the path to the file being added
(relative to the source directory).  It should return <code class="docutils literal notranslate"><span class="pre">True</span></code> if the
file is to be added.</p>
<p>The optional <em>compressed</em> argument determines whether files are
compressed.  If set to <code class="docutils literal notranslate"><span class="pre">True</span></code>, files in the archive are compressed
with the deflate method; otherwise, files are stored uncompressed.
This argument has no effect when copying an existing archive.</p>
<p>If a file object is specified for <em>source</em> or <em>target</em>, it is the
caller’s responsibility to close it after calling create_archive.</p>
<p>When copying an existing archive, file objects supplied only need
<code class="docutils literal notranslate"><span class="pre">read</span></code> and <code class="docutils literal notranslate"><span class="pre">readline</span></code>, or <code class="docutils literal notranslate"><span class="pre">write</span></code> methods.  When creating an
archive from a directory, if the target is a file object it will be
passed to the <code class="docutils literal notranslate"><span class="pre">zipfile.ZipFile</span></code> class, and must supply the methods
needed by that class.</p>
<div class="versionadded">
<p><span class="versionmodified added">New in version 3.7: </span>Added the <em>filter</em> and <em>compressed</em> arguments.</p>
</div>
</dd></dl>

<dl class="function">
<dt id="zipapp.get_interpreter">
<code class="sig-prename descclassname">zipapp.</code><code class="sig-name descname">get_interpreter</code><span class="sig-paren">(</span><em class="sig-param">archive</em><span class="sig-paren">)</span><a class="headerlink" href="#zipapp.get_interpreter" title="Permalink to this definition">¶</a></dt>
<dd><p>Return the interpreter specified in the <code class="docutils literal notranslate"><span class="pre">#!</span></code> line at the start of the
archive.  If there is no <code class="docutils literal notranslate"><span class="pre">#!</span></code> line, return <a class="reference internal" href="constants.html#None" title="None"><code class="xref py py-const docutils literal notranslate"><span class="pre">None</span></code></a>.
The <em>archive</em> argument can be a filename or a file-like object open
for reading in bytes mode.  It is assumed to be at the start of the archive.</p>
</dd></dl>

</section>
<section id="examples">
<span id="zipapp-examples"></span><h2>Examples<a class="headerlink" href="#examples" title="Permalink to this headline">¶</a></h2>
<p>Pack up a directory into an archive, and run it.</p>
<div class="highlight-shell-session notranslate"><div class="highlight"><pre><span></span><span class="gp">$ </span>python -m zipapp myapp
<span class="gp">$ </span>python myapp.pyz
<span class="go">&lt;output from myapp&gt;</span>
</pre></div>
</div>
<p>The same can be done using the <a class="reference internal" href="#zipapp.create_archive" title="zipapp.create_archive"><code class="xref py py-func docutils literal notranslate"><span class="pre">create_archive()</span></code></a> function:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span> <span class="nn">zipapp</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">zipapp</span><span class="o">.</span><span class="n">create_archive</span><span class="p">(</span><span class="s1">&#39;myapp&#39;</span><span class="p">,</span> <span class="s1">&#39;myapp.pyz&#39;</span><span class="p">)</span>
</pre></div>
</div>
<p>To make the application directly executable on POSIX, specify an interpreter
to use.</p>
<div class="highlight-shell-session notranslate"><div class="highlight"><pre><span></span><span class="gp">$ </span>python -m zipapp myapp -p <span class="s2">&quot;/usr/bin/env python&quot;</span>
<span class="gp">$ </span>./myapp.pyz
<span class="go">&lt;output from myapp&gt;</span>
</pre></div>
</div>
<p>To replace the shebang line on an existing archive, create a modified archive
using the <a class="reference internal" href="#zipapp.create_archive" title="zipapp.create_archive"><code class="xref py py-func docutils literal notranslate"><span class="pre">create_archive()</span></code></a> function:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span> <span class="nn">zipapp</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">zipapp</span><span class="o">.</span><span class="n">create_archive</span><span class="p">(</span><span class="s1">&#39;old_archive.pyz&#39;</span><span class="p">,</span> <span class="s1">&#39;new_archive.pyz&#39;</span><span class="p">,</span> <span class="s1">&#39;/usr/bin/python3&#39;</span><span class="p">)</span>
</pre></div>
</div>
<p>To update the file in place, do the replacement in memory using a <code class="xref py py-class docutils literal notranslate"><span class="pre">BytesIO</span></code>
object, and then overwrite the source afterwards.  Note that there is a risk
when overwriting a file in place that an error will result in the loss of
the original file.  This code does not protect against such errors, but
production code should do so.  Also, this method will only work if the archive
fits in memory:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span> <span class="nn">zipapp</span>
<span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span> <span class="nn">io</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">temp</span> <span class="o">=</span> <span class="n">io</span><span class="o">.</span><span class="n">BytesIO</span><span class="p">()</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">zipapp</span><span class="o">.</span><span class="n">create_archive</span><span class="p">(</span><span class="s1">&#39;myapp.pyz&#39;</span><span class="p">,</span> <span class="n">temp</span><span class="p">,</span> <span class="s1">&#39;/usr/bin/python2&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s1">&#39;myapp.pyz&#39;</span><span class="p">,</span> <span class="s1">&#39;wb&#39;</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
<span class="gp">&gt;&gt;&gt; </span>    <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">temp</span><span class="o">.</span><span class="n">getvalue</span><span class="p">())</span>
</pre></div>
</div>
</section>
<section id="specifying-the-interpreter">
<span id="zipapp-specifying-the-interpreter"></span><h2>Specifying the Interpreter<a class="headerlink" href="#specifying-the-interpreter" title="Permalink to this headline">¶</a></h2>
<p>Note that if you specify an interpreter and then distribute your application
archive, you need to ensure that the interpreter used is portable.  The Python
launcher for Windows supports most common forms of POSIX <code class="docutils literal notranslate"><span class="pre">#!</span></code> line, but there
are other issues to consider:</p>
<ul class="simple">
<li><p>If you use “/usr/bin/env python” (or other forms of the “python” command,
such as “/usr/bin/python”), you need to consider that your users may have
either Python 2 or Python 3 as their default, and write your code to work
under both versions.</p></li>
<li><p>If you use an explicit version, for example “/usr/bin/env python3” your
application will not work for users who do not have that version.  (This
may be what you want if you have not made your code Python 2 compatible).</p></li>
<li><p>There is no way to say “python X.Y or later”, so be careful of using an
exact version like “/usr/bin/env python3.4” as you will need to change your
shebang line for users of Python 3.5, for example.</p></li>
</ul>
<p>Typically, you should use an “/usr/bin/env python2” or “/usr/bin/env python3”,
depending on whether your code is written for Python 2 or 3.</p>
</section>
<section id="creating-standalone-applications-with-zipapp">
<h2>Creating Standalone Applications with zipapp<a class="headerlink" href="#creating-standalone-applications-with-zipapp" title="Permalink to this headline">¶</a></h2>
<p>Using the <a class="reference internal" href="#module-zipapp" title="zipapp: Manage executable Python zip archives"><code class="xref py py-mod docutils literal notranslate"><span class="pre">zipapp</span></code></a> module, it is possible to create self-contained Python
programs, which can be distributed to end users who only need to have a
suitable version of Python installed on their system.  The key to doing this
is to bundle all of the application’s dependencies into the archive, along
with the application code.</p>
<p>The steps to create a standalone archive are as follows:</p>
<ol class="arabic">
<li><p>Create your application in a directory as normal, so you have a <code class="docutils literal notranslate"><span class="pre">myapp</span></code>
directory containing a <code class="docutils literal notranslate"><span class="pre">__main__.py</span></code> file, and any supporting application
code.</p></li>
<li><p>Install all of your application’s dependencies into the <code class="docutils literal notranslate"><span class="pre">myapp</span></code> directory,
using pip:</p>
<div class="highlight-shell-session notranslate"><div class="highlight"><pre><span></span><span class="gp">$ </span>python -m pip install -r requirements.txt --target myapp
</pre></div>
</div>
<p>(this assumes you have your project requirements in a <code class="docutils literal notranslate"><span class="pre">requirements.txt</span></code>
file - if not, you can just list the dependencies manually on the pip command
line).</p>
</li>
<li><p>Optionally, delete the <code class="docutils literal notranslate"><span class="pre">.dist-info</span></code> directories created by pip in the
<code class="docutils literal notranslate"><span class="pre">myapp</span></code> directory. These hold metadata for pip to manage the packages, and
as you won’t be making any further use of pip they aren’t required -
although it won’t do any harm if you leave them.</p></li>
<li><p>Package the application using:</p>
<div class="highlight-shell-session notranslate"><div class="highlight"><pre><span></span><span class="gp">$ </span>python -m zipapp -p <span class="s2">&quot;interpreter&quot;</span> myapp
</pre></div>
</div>
</li>
</ol>
<p>This will produce a standalone executable, which can be run on any machine with
the appropriate interpreter available. See <a class="reference internal" href="#zipapp-specifying-the-interpreter"><span class="std std-ref">Specifying the Interpreter</span></a>
for details. It can be shipped to users as a single file.</p>
<p>On Unix, the <code class="docutils literal notranslate"><span class="pre">myapp.pyz</span></code> file is executable as it stands.  You can rename the
file to remove the <code class="docutils literal notranslate"><span class="pre">.pyz</span></code> extension if you prefer a “plain” command name.  On
Windows, the <code class="docutils literal notranslate"><span class="pre">myapp.pyz[w]</span></code> file is executable by virtue of the fact that
the Python interpreter registers the <code class="docutils literal notranslate"><span class="pre">.pyz</span></code> and <code class="docutils literal notranslate"><span class="pre">.pyzw</span></code> file extensions
when installed.</p>
<section id="making-a-windows-executable">
<h3>Making a Windows executable<a class="headerlink" href="#making-a-windows-executable" title="Permalink to this headline">¶</a></h3>
<p>On Windows, registration of the <code class="docutils literal notranslate"><span class="pre">.pyz</span></code> extension is optional, and
furthermore, there are certain places that don’t recognise registered
extensions “transparently” (the simplest example is that
<code class="docutils literal notranslate"><span class="pre">subprocess.run(['myapp'])</span></code> won’t find your application - you need to
explicitly specify the extension).</p>
<p>On Windows, therefore, it is often preferable to create an executable from the
zipapp.  This is relatively easy, although it does require a C compiler.  The
basic approach relies on the fact that zipfiles can have arbitrary data
prepended, and Windows exe files can have arbitrary data appended.  So by
creating a suitable launcher and tacking the <code class="docutils literal notranslate"><span class="pre">.pyz</span></code> file onto the end of it,
you end up with a single-file executable that runs your application.</p>
<p>A suitable launcher can be as simple as the following:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="c1">#define Py_LIMITED_API 1</span>
<span class="c1">#include &quot;Python.h&quot;</span>

<span class="c1">#define WIN32_LEAN_AND_MEAN</span>
<span class="c1">#include &lt;windows.h&gt;</span>

<span class="c1">#ifdef WINDOWS</span>
<span class="nb">int</span> <span class="n">WINAPI</span> <span class="n">wWinMain</span><span class="p">(</span>
    <span class="n">HINSTANCE</span> <span class="n">hInstance</span><span class="p">,</span>      <span class="o">/*</span> <span class="n">handle</span> <span class="n">to</span> <span class="n">current</span> <span class="n">instance</span> <span class="o">*/</span>
    <span class="n">HINSTANCE</span> <span class="n">hPrevInstance</span><span class="p">,</span>  <span class="o">/*</span> <span class="n">handle</span> <span class="n">to</span> <span class="n">previous</span> <span class="n">instance</span> <span class="o">*/</span>
    <span class="n">LPWSTR</span> <span class="n">lpCmdLine</span><span class="p">,</span>         <span class="o">/*</span> <span class="n">pointer</span> <span class="n">to</span> <span class="n">command</span> <span class="n">line</span> <span class="o">*/</span>
    <span class="nb">int</span> <span class="n">nCmdShow</span>              <span class="o">/*</span> <span class="n">show</span> <span class="n">state</span> <span class="n">of</span> <span class="n">window</span> <span class="o">*/</span>
<span class="p">)</span>
<span class="c1">#else</span>
<span class="nb">int</span> <span class="n">wmain</span><span class="p">()</span>
<span class="c1">#endif</span>
<span class="p">{</span>
    <span class="n">wchar_t</span> <span class="o">**</span><span class="n">myargv</span> <span class="o">=</span> <span class="n">_alloca</span><span class="p">((</span><span class="n">__argc</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="o">*</span> <span class="n">sizeof</span><span class="p">(</span><span class="n">wchar_t</span><span class="o">*</span><span class="p">));</span>
    <span class="n">myargv</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">__wargv</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span>
    <span class="n">memcpy</span><span class="p">(</span><span class="n">myargv</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">__wargv</span><span class="p">,</span> <span class="n">__argc</span> <span class="o">*</span> <span class="n">sizeof</span><span class="p">(</span><span class="n">wchar_t</span> <span class="o">*</span><span class="p">));</span>
    <span class="k">return</span> <span class="n">Py_Main</span><span class="p">(</span><span class="n">__argc</span><span class="o">+</span><span class="mi">1</span><span class="p">,</span> <span class="n">myargv</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>
</div>
<p>If you define the <code class="docutils literal notranslate"><span class="pre">WINDOWS</span></code> preprocessor symbol, this will generate a
GUI executable, and without it, a console executable.</p>
<p>To compile the executable, you can either just use the standard MSVC
command line tools, or you can take advantage of the fact that distutils
knows how to compile Python source:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">distutils.ccompiler</span> <span class="kn">import</span> <span class="n">new_compiler</span>
<span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span> <span class="nn">distutils.sysconfig</span>
<span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span> <span class="nn">sys</span>
<span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span> <span class="nn">os</span>
<span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">pathlib</span> <span class="kn">import</span> <span class="n">Path</span>

<span class="gp">&gt;&gt;&gt; </span><span class="k">def</span> <span class="nf">compile</span><span class="p">(</span><span class="n">src</span><span class="p">):</span>
<span class="gp">&gt;&gt;&gt; </span>    <span class="n">src</span> <span class="o">=</span> <span class="n">Path</span><span class="p">(</span><span class="n">src</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span>    <span class="n">cc</span> <span class="o">=</span> <span class="n">new_compiler</span><span class="p">()</span>
<span class="gp">&gt;&gt;&gt; </span>    <span class="n">exe</span> <span class="o">=</span> <span class="n">src</span><span class="o">.</span><span class="n">stem</span>
<span class="gp">&gt;&gt;&gt; </span>    <span class="n">cc</span><span class="o">.</span><span class="n">add_include_dir</span><span class="p">(</span><span class="n">distutils</span><span class="o">.</span><span class="n">sysconfig</span><span class="o">.</span><span class="n">get_python_inc</span><span class="p">())</span>
<span class="gp">&gt;&gt;&gt; </span>    <span class="n">cc</span><span class="o">.</span><span class="n">add_library_dir</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">base_exec_prefix</span><span class="p">,</span> <span class="s1">&#39;libs&#39;</span><span class="p">))</span>
<span class="gp">&gt;&gt;&gt; </span>    <span class="c1"># First the CLI executable</span>
<span class="gp">&gt;&gt;&gt; </span>    <span class="n">objs</span> <span class="o">=</span> <span class="n">cc</span><span class="o">.</span><span class="n">compile</span><span class="p">([</span><span class="nb">str</span><span class="p">(</span><span class="n">src</span><span class="p">)])</span>
<span class="gp">&gt;&gt;&gt; </span>    <span class="n">cc</span><span class="o">.</span><span class="n">link_executable</span><span class="p">(</span><span class="n">objs</span><span class="p">,</span> <span class="n">exe</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span>    <span class="c1"># Now the GUI executable</span>
<span class="gp">&gt;&gt;&gt; </span>    <span class="n">cc</span><span class="o">.</span><span class="n">define_macro</span><span class="p">(</span><span class="s1">&#39;WINDOWS&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span>    <span class="n">objs</span> <span class="o">=</span> <span class="n">cc</span><span class="o">.</span><span class="n">compile</span><span class="p">([</span><span class="nb">str</span><span class="p">(</span><span class="n">src</span><span class="p">)])</span>
<span class="gp">&gt;&gt;&gt; </span>    <span class="n">cc</span><span class="o">.</span><span class="n">link_executable</span><span class="p">(</span><span class="n">objs</span><span class="p">,</span> <span class="n">exe</span> <span class="o">+</span> <span class="s1">&#39;w&#39;</span><span class="p">)</span>

<span class="gp">&gt;&gt;&gt; </span><span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s2">&quot;__main__&quot;</span><span class="p">:</span>
<span class="gp">&gt;&gt;&gt; </span>    <span class="nb">compile</span><span class="p">(</span><span class="s2">&quot;zastub.c&quot;</span><span class="p">)</span>
</pre></div>
</div>
<p>The resulting launcher uses the “Limited ABI”, so it will run unchanged with
any version of Python 3.x.  All it needs is for Python (<code class="docutils literal notranslate"><span class="pre">python3.dll</span></code>) to be
on the user’s <code class="docutils literal notranslate"><span class="pre">PATH</span></code>.</p>
<p>For a fully standalone distribution, you can distribute the launcher with your
application appended, bundled with the Python “embedded” distribution.  This
will run on any PC with the appropriate architecture (32 bit or 64 bit).</p>
</section>
<section id="caveats">
<h3>Caveats<a class="headerlink" href="#caveats" title="Permalink to this headline">¶</a></h3>
<p>There are some limitations to the process of bundling your application into
a single file.  In most, if not all, cases they can be addressed without
needing major changes to your application.</p>
<ol class="arabic simple">
<li><p>If your application depends on a package that includes a C extension, that
package cannot be run from a zip file (this is an OS limitation, as executable
code must be present in the filesystem for the OS loader to load it). In this
case, you can exclude that dependency from the zipfile, and either require
your users to have it installed, or ship it alongside your zipfile and add code
to your <code class="docutils literal notranslate"><span class="pre">__main__.py</span></code> to include the directory containing the unzipped
module in <code class="docutils literal notranslate"><span class="pre">sys.path</span></code>. In this case, you will need to make sure to ship
appropriate binaries for your target architecture(s) (and potentially pick the
correct version to add to <code class="docutils literal notranslate"><span class="pre">sys.path</span></code> at runtime, based on the user’s machine).</p></li>
<li><p>If you are shipping a Windows executable as described above, you either need to
ensure that your users have <code class="docutils literal notranslate"><span class="pre">python3.dll</span></code> on their PATH (which is not the
default behaviour of the installer) or you should bundle your application with
the embedded distribution.</p></li>
<li><p>The suggested launcher above uses the Python embedding API.  This means that in
your application, <code class="docutils literal notranslate"><span class="pre">sys.executable</span></code> will be your application, and <em>not</em> a
conventional Python interpreter.  Your code and its dependencies need to be
prepared for this possibility.  For example, if your application uses the
<a class="reference internal" href="multiprocessing.html#module-multiprocessing" title="multiprocessing: Process-based parallelism."><code class="xref py py-mod docutils literal notranslate"><span class="pre">multiprocessing</span></code></a> module, it will need to call
<a class="reference internal" href="multiprocessing.html#multiprocessing.set_executable" title="multiprocessing.set_executable"><code class="xref py py-func docutils literal notranslate"><span class="pre">multiprocessing.set_executable()</span></code></a> to let the module know where to find the
standard Python interpreter.</p></li>
</ol>
</section>
</section>
<section id="the-python-zip-application-archive-format">
<h2>The Python Zip Application Archive Format<a class="headerlink" href="#the-python-zip-application-archive-format" title="Permalink to this headline">¶</a></h2>
<p>Python has been able to execute zip files which contain a <code class="docutils literal notranslate"><span class="pre">__main__.py</span></code> file
since version 2.6.  In order to be executed by Python, an application archive
simply has to be a standard zip file containing a <code class="docutils literal notranslate"><span class="pre">__main__.py</span></code> file which
will be run as the entry point for the application.  As usual for any Python
script, the parent of the script (in this case the zip file) will be placed on
<a class="reference internal" href="sys.html#sys.path" title="sys.path"><code class="xref py py-data docutils literal notranslate"><span class="pre">sys.path</span></code></a> and thus further modules can be imported from the zip file.</p>
<p>The zip file format allows arbitrary data to be prepended to a zip file.  The
zip application format uses this ability to prepend a standard POSIX “shebang”
line to the file (<code class="docutils literal notranslate"><span class="pre">#!/path/to/interpreter</span></code>).</p>
<p>Formally, the Python zip application format is therefore:</p>
<ol class="arabic simple">
<li><p>An optional shebang line, containing the characters <code class="docutils literal notranslate"><span class="pre">b'#!'</span></code> followed by an
interpreter name, and then a newline (<code class="docutils literal notranslate"><span class="pre">b'\n'</span></code>) character.  The interpreter
name can be anything acceptable to the OS “shebang” processing, or the Python
launcher on Windows.  The interpreter should be encoded in UTF-8 on Windows,
and in <a class="reference internal" href="sys.html#sys.getfilesystemencoding" title="sys.getfilesystemencoding"><code class="xref py py-func docutils literal notranslate"><span class="pre">sys.getfilesystemencoding()</span></code></a> on POSIX.</p></li>
<li><p>Standard zipfile data, as generated by the <a class="reference internal" href="zipfile.html#module-zipfile" title="zipfile: Read and write ZIP-format archive files."><code class="xref py py-mod docutils literal notranslate"><span class="pre">zipfile</span></code></a> module.  The
zipfile content <em>must</em> include a file called <code class="docutils literal notranslate"><span class="pre">__main__.py</span></code> (which must be
in the “root” of the zipfile - i.e., it cannot be in a subdirectory).  The
zipfile data can be compressed or uncompressed.</p></li>
</ol>
<p>If an application archive has a shebang line, it may have the executable bit set
on POSIX systems, to allow it to be executed directly.</p>
<p>There is no requirement that the tools in this module are used to create
application archives - the module is a convenience, but archives in the above
format created by any means are acceptable to Python.</p>
</section>
</section>


          </div>
        </div>
      </div>
      <div class="sphinxsidebar" role="navigation" aria-label="main navigation">
        <div class="sphinxsidebarwrapper">
  <h3><a href="../contents.html">Table of Contents</a></h3>
  <ul>
<li><a class="reference internal" href="#"><code class="xref py py-mod docutils literal notranslate"><span class="pre">zipapp</span></code> — Manage executable Python zip archives</a><ul>
<li><a class="reference internal" href="#basic-example">Basic Example</a></li>
<li><a class="reference internal" href="#command-line-interface">Command-Line Interface</a></li>
<li><a class="reference internal" href="#python-api">Python API</a></li>
<li><a class="reference internal" href="#examples">Examples</a></li>
<li><a class="reference internal" href="#specifying-the-interpreter">Specifying the Interpreter</a></li>
<li><a class="reference internal" href="#creating-standalone-applications-with-zipapp">Creating Standalone Applications with zipapp</a><ul>
<li><a class="reference internal" href="#making-a-windows-executable">Making a Windows executable</a></li>
<li><a class="reference internal" href="#caveats">Caveats</a></li>
</ul>
</li>
<li><a class="reference internal" href="#the-python-zip-application-archive-format">The Python Zip Application Archive Format</a></li>
</ul>
</li>
</ul>

  <h4>Previous topic</h4>
  <p class="topless"><a href="venv.html"
                        title="previous chapter"><code class="xref py py-mod docutils literal notranslate"><span class="pre">venv</span></code> — Creation of virtual environments</a></p>
  <h4>Next topic</h4>
  <p class="topless"><a href="python.html"
                        title="next chapter">Python Runtime Services</a></p>
  <div role="note" aria-label="source link">
    <h3>This Page</h3>
    <ul class="this-page-menu">
      <li><a href="../bugs.html">Report a Bug</a></li>
      <li>
        <a href="https://github.com/python/cpython/blob/3.9/Doc/library/zipapp.rst"
            rel="nofollow">Show Source
        </a>
      </li>
    </ul>
  </div>
        </div>
      </div>
      <div class="clearer"></div>
    </div>  
    <div class="related" role="navigation" aria-label="related navigation">
      <h3>Navigation</h3>
      <ul>
        <li class="right" style="margin-right: 10px">
          <a href="../genindex.html" title="General Index"
             >index</a></li>
        <li class="right" >
          <a href="../py-modindex.html" title="Python Module Index"
             >modules</a> |</li>
        <li class="right" >
          <a href="python.html" title="Python Runtime Services"
             >next</a> |</li>
        <li class="right" >
          <a href="venv.html" title="venv — Creation of virtual environments"
             >previous</a> |</li>

    <li><img src="../_static/py.png" alt=""
             style="vertical-align: middle; margin-top: -1px"/></li>
    <li><a href="https://www.python.org/">Python</a> &#187;</li>
    

    <li>
      <a href="../index.html">3.9.6 Documentation</a> &#187;
    </li>

          <li class="nav-item nav-item-1"><a href="index.html" >The Python Standard Library</a> &#187;</li>
          <li class="nav-item nav-item-2"><a href="distribution.html" >Software Packaging and Distribution</a> &#187;</li>
    <li class="right">
        

    <div class="inline-search" style="display: none" role="search">
        <form class="inline-search" action="../search.html" method="get">
          <input placeholder="Quick search" type="text" name="q" />
          <input type="submit" value="Go" />
          <input type="hidden" name="check_keywords" value="yes" />
          <input type="hidden" name="area" value="default" />
        </form>
    </div>
    <script type="text/javascript">$('.inline-search').show(0);</script>
         |
    </li>

      </ul>
    </div>  
    <div class="footer">
    &copy; <a href="../copyright.html">Copyright</a> 2001-2021, Python Software Foundation.
    <br />

    The Python Software Foundation is a non-profit corporation.
<a href="https://www.python.org/psf/donations/">Please donate.</a>
<br />
    <br />

    Last updated on Jun 28, 2021.
    <a href="https://docs.python.org/3/bugs.html">Found a bug</a>?
    <br />

    Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 2.3.1.
    </div>

  </body>
</html>